package com.fivefu.core.gb28181.utils;

import com.fivefu.base.common.utils.str.StrUtils;
import com.fivefu.core.gb28181.constant.PTZEnum;

import java.math.BigInteger;

public class PTZUtils {

    /**
     * 16进制转10进制
     * @param hexStr
     * @return
     */
    public static BigInteger HexToNum(String hexStr){
        BigInteger num = new BigInteger(hexStr,16);
        return num;
    }

    /**
     * 16进制转2进制
     * @param hexStr
     * @return
     */
    public static String HexToBit(String hexStr){
        BigInteger num = HexToNum(hexStr);
        String str = NumToBinary(num);
        return str;
    }

    /**
     * 10进制转16进制
     * @param num
     * @return
     */
    public static String NumToHex(BigInteger num){
        String HStr = String.format("%02X", num);
        return HStr;
    }

    /**
     * 10进制转2进制
     * @param num
     */
    public static String NumToBinary(BigInteger num){
        String bit = num.toString(2);
//        String binaryStr = new StringBuilder(bit).reverse().toString();
//        binaryStr = "00000000" + binaryStr;
        String binaryStr = "00000000" + bit;
        return binaryStr.substring(binaryStr.length() - 8);
    }

    /**
     * 2进制转10进制
     * @param bit
     * @return
     */
    public static Integer BinaryToNum(String bit){
        Integer num = Integer.parseInt(bit,2);
        return num;
    }

    /**
     * 2进制转16进制
     * @param bit
     */
    public static String BinaryToHex(String bit){
        Integer num = BinaryToNum(bit);
        String HStr = NumToHex(BigInteger.valueOf(num.longValue()));
        return HStr;
    }

    /**
     * 字节2,组合码1，
     * 高4位是版本信息，低4位是校验位。
     * 本标准的版本号是1.0，版本信息为0H；
     * 校验位=（字节1的高4位+字节1的低4位+字节2的高4位）%16；
     */
    public static String ptzByte2(){
        String version = HexToBit("A5");

        Integer num1 = BinaryToNum(version.substring(0, 4));
        Integer num2 = BinaryToNum(version.substring(4));
        Integer num3 = BinaryToNum("0");

        Integer sum = (num1 + num2 + num3)%16;
        String byte2 = NumToHex(BigInteger.valueOf(sum.longValue()));
        return byte2;
    }

    /**
     * 生成控制云台指令
     * @param controlCmd 云台指令
     * @param xSpeed 水平控制速度
     * @param ySpeed 垂直控制速度
     * @param cSpped 变焦速度
     * @return
     */
    public static String ptzCmd(String controlCmd, Integer xSpeed, Integer ySpeed, Integer cSpped){
        String address = "00";

        if (xSpeed != null) xSpeed = 0;
        if (ySpeed != null) ySpeed = 0;
        if (cSpped != null) cSpped = 0;
        if (StrUtils.isNull(controlCmd)) controlCmd = "00";

        String byte1 = "A5";//字节1,指令的首字节为A5H；
        String byte2 = ptzByte2();//字节2,组合码1，高4位是版本信息，低4位是校验位。本标准的版本号是1.0，版本信息为0H；校验位=（字节1的高4位+字节1的低4位+字节2的高4位）%16；
        String byte3 = address;//字节3,地址的低8位；地址范围000H—FFFH（即0—4095），其中000H地址作为广播地址。
        String byte5 = NumToHex(BigInteger.valueOf(xSpeed.longValue()));//字节5,水平控制速度相对值
        String byte6 = NumToHex(BigInteger.valueOf(ySpeed.longValue()));//字节6,垂直控制速度相对值
        String byte7 = BinaryToHex(NumToBinary(BigInteger.valueOf(cSpped)).substring(0,4) + HexToBit(address).substring(4));//字节7,变焦速度，速度范围由慢到快为0H-FH；低4位为地址的高4位

        String byte8 = NumToHex(BigInteger.valueOf((
                HexToNum(byte1).longValue() + HexToNum(byte2).longValue() + HexToNum(byte3).longValue() +
                HexToNum(controlCmd).longValue() + HexToNum(byte5).longValue() + HexToNum(byte6).longValue() +
                HexToNum(byte7).longValue()
        )%256));//字节8,（字节1+字节2+字节3+字节4+字节5+字节6+字节7）%256

        StringBuffer sb = new StringBuffer();
        sb.append(byte1);//字节1,指令的首字节为A5H；
        sb.append(byte2);//字节2,组合码1，高4位是版本信息，低4位是校验位。本标准的版本号是1.0，版本信息为0H；校验位=（字节1的高4位+字节1的低4位+字节2的高4位）%16；
        sb.append(byte3);//字节3,地址的低8位；地址范围000H—FFFH（即0—4095），其中000H地址作为广播地址。
        sb.append(controlCmd);//字节4,指令码,0,0,缩小（OUT）,放大（IN） 上（Up）,下（Down）,左（Left）,右（Right）
        sb.append(byte5);//字节5,水平控制速度相对值
        sb.append(byte6);//字节6,垂直控制速度相对值
        sb.append(byte7);//字节7,变焦速度，速度范围由慢到快为0H-FH；低4位为地址的高4位
        sb.append(byte8);//字节8,（字节1+字节2+字节3+字节4+字节5+字节6+字节7）%256
        return sb.toString();
    }



    /**
     * 云台操作指令
     * @param ptzName
     * @param active 0:停止,1:启动
     * @param speed 速度
     * @return
     */
    public static String ptzControlCmd(String ptzName, Integer active, Integer speed){
        PTZEnum ptzEnum = PTZEnum.valueOf(ptzName);
        String startCmd = ptzEnum.getPtzStartCmd();

        String controlCmd = startCmd + "000000";

        String cmd = "";
        if (active.equals(0)){
            controlCmd = BinaryToHex(controlCmd);
            cmd = ptzCmd(controlCmd,0,0,0);
        }else if (active.equals(1)){
            Integer xSpeed = 0 , ySpeed = 0 , cSpeed = 0;
            String speedType = ptzEnum.getSpeedType();
            if (speedType.contains("x")) xSpeed = speed;
            if (speedType.contains("y")) ySpeed = speed;
            if (speedType.contains("c")) cSpeed = speed;

            if (startCmd.equals("00")){//ptz
                if (ptzName.contains("RIGHT")) controlCmd = replaceCharAt(controlCmd, 7,active + "");
                if (ptzName.contains("LEFT")) controlCmd = replaceCharAt(controlCmd, 6,active + "");
                if (ptzName.contains("UP")) controlCmd = replaceCharAt(controlCmd, 4,active + "");
                if (ptzName.contains("DOWN")) controlCmd = replaceCharAt(controlCmd, 5,active + "");
                if (ptzName.contains("OUT")) controlCmd = replaceCharAt(controlCmd, 2,active + "");
                if (ptzName.contains("IN")) controlCmd = replaceCharAt(controlCmd, 3,active + "");
                controlCmd = BinaryToHex(controlCmd);
                cmd = ptzCmd(controlCmd,xSpeed,ySpeed,cSpeed);
            }else if (startCmd.equals("01")){//fi
                if (ptzName.equals("FOCUSNEAR")) controlCmd = replaceCharAt(controlCmd, 6,active + "");//焦点前移
                if (ptzName.equals("FOCUSFAR")) controlCmd = replaceCharAt(controlCmd, 7,active + "");//焦点后移

                if (ptzName.equals("IRISENLARCE")) controlCmd = replaceCharAt(controlCmd, 5,active + "");//光圈扩大
                if (ptzName.equals("IRISREDUCE")) controlCmd = replaceCharAt(controlCmd, 4,active + "");//光圈缩小
                controlCmd = BinaryToHex(controlCmd);
                cmd = ptzCmd(controlCmd,xSpeed,ySpeed,cSpeed);
            }
        }

        return cmd;
    }

    /**
     * 替换某下标的字符
     * @param str 原字符
     * @param inx 需替换字符下标
     * @param replaceStr 替换的字符
     * @return
     */
    public static String replaceCharAt(String str, int inx, String replaceStr){
        str = str.substring(0,inx) + replaceStr + str.substring(inx + 1);
        return str;
    }



    public static void main(String[] args) {
        String str = "12345678";
        Integer num = 1;
        str = str.substring(0,num) + "1" + str.substring(num + 1);
        System.out.println(str);
    }

}
